/**
 * LGPL
 * @Author jw12
 */
package org.biodas.jdas.creators.writers;

import java.io.*;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import org.biodas.jdas.client.adapters.features.DasGFFAdapter;


import org.biodas.jdas.exceptions.DASClientException;
import org.biodas.jdas.schema.sources.SOURCES;

import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.annotate.JsonAutoDetect;
import org.codehaus.jackson.map.AnnotationIntrospector;
import org.codehaus.jackson.map.DeserializationConfig;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.introspect.JacksonAnnotationIntrospector;
import org.codehaus.jackson.map.SerializationConfig;
import org.codehaus.jackson.xc.JaxbAnnotationIntrospector;


/**
 * Class for writing Sources to xml or json LPGL
 * 
 * @author JWarren
 * 
 */
public class DasWriter {

	public void writeXmlToStandardOut(Object jdasObjects, String packageString)
			throws DASClientException {
		
			this.writeXmlToOutputStream(jdasObjects,packageString, System.out);
		
	}

	public void writeXmlToFile(Object jdasObjects,String packageString,
			String pathAndName) throws FileNotFoundException,
			DASClientException {

		OutputStream os = null;

		os = new FileOutputStream(pathAndName);

		this.writeXmlToOutputStream(jdasObjects,packageString, os);

	}

	/**
	 * @param jdasObjects
	 * @param pathAndName
	 */
	public void writeJsonToOutputStream(Object jdasObjects,
			OutputStream out) throws FileNotFoundException, DASClientException {
        ObjectMapper mapper = getMapper();

		// mapper.configure(f, state)
		try {
			mapper.writeValue(out, jdasObjects);

		} catch (JsonGenerationException e) {
		
			e.printStackTrace();
		} catch (JsonMappingException e) {
		
			e.printStackTrace();
		} catch (IOException e) {
			
			e.printStackTrace();
		}

	}
        
        /**
	 * @param jdasObjects
	 * @param pathAndName
	 */
	public void writeJsonToBufferedWriter(Object jdasObjects,
			BufferedWriter out) throws FileNotFoundException, DASClientException {
        ObjectMapper mapper = getMapper();

		// mapper.configure(f, state)
		try {
			mapper.writeValue(out, jdasObjects);

		} catch (JsonGenerationException e) {
		
			e.printStackTrace();
		} catch (JsonMappingException e) {
		
			e.printStackTrace();
		} catch (IOException e) {
			
			e.printStackTrace();
		}

	}

    private ObjectMapper getMapper() {    
        ObjectMapper mapper = new ObjectMapper();     
        AnnotationIntrospector primary = new JacksonAnnotationIntrospector();
        AnnotationIntrospector secondary = new JaxbAnnotationIntrospector();
        AnnotationIntrospector pair = new AnnotationIntrospector.Pair(primary, secondary);
        mapper.setAnnotationIntrospector(pair);
       
        mapper.configure(
                        DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
       mapper.configure(SerializationConfig.Feature.WRAP_ROOT_VALUE,
                       true);
        mapper.configure(SerializationConfig.Feature.WRITE_NULL_PROPERTIES,
                        false);
        mapper.configure(SerializationConfig.Feature.WRITE_EMPTY_JSON_ARRAYS,
                        false);
        mapper.configure(SerializationConfig.Feature.WRITE_NULL_MAP_VALUES,
                        false);
        mapper.configure(SerializationConfig.Feature.AUTO_DETECT_FIELDS, false);
        mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true);
        //mapper.setVisibilityChecker(mapper.getVisibilityChecker().with(JsonAutoDetect.Visibility.NONE));
        
        return mapper;
    }

	/**
	 * @param converted
	 */
	public void writeJsonToStandardOut(Object jdasObjects)
			throws DASClientException {

		try {
			this.writeJsonToOutputStream(jdasObjects, System.out);
		} catch (FileNotFoundException e) {
			// won't get thrown as we are writing to stdout
			e.printStackTrace();
		}
	}

	public void writeXmlToOutputStream(Object jdasObjects, String packageString, OutputStream out) throws DASClientException {
		JAXBContext jc = null;
		try {
			jc = JAXBContext.newInstance(packageString);
		} catch (JAXBException e) {
			e.printStackTrace();
		}
		Marshaller m = null;
		try {
			m = jc.createMarshaller();
		} catch (JAXBException e) {
			e.printStackTrace();
		}

		try {
			m.marshal(jdasObjects, out);
		} catch (JAXBException e) {
			throw new DASClientException(e.getMessage(), e.getCause());
		}

	}

	public void writeJsonToFile(Object jdasObjects,
			String pathAndName) throws DASClientException,
			FileNotFoundException {
		OutputStream os = null;

		os = new FileOutputStream(pathAndName);

		try {
			this.writeJsonToOutputStream(jdasObjects, os);
		} catch (FileNotFoundException e) {
			// won't get thrown as we are writing to stdout
			e.printStackTrace();
		}
	}

    public void writeXmlToBufferedWriter(Object jdasObjects, String packageString, BufferedWriter out) throws DASClientException {
        JAXBContext jc = null;
		try {
			jc = JAXBContext.newInstance(packageString);
		} catch (JAXBException e) {
			throw new DASClientException(e.getMessage(), e.getCause());
		}
		Marshaller m = null;
		try {
			m = jc.createMarshaller();
		} catch (JAXBException e) {
			throw new DASClientException(e.getMessage(), e.getCause());
		}

		try {
			m.marshal(jdasObjects, out);
		} catch (JAXBException e) {
			throw new DASClientException(e.getMessage(), e.getCause());
		}
    }
}
